package cn.pink.common.config;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.TreeMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import cn.pink.core.conf.ConfBase;
import cn.pink.core.conf.ConfigJSON;
import cn.pink.core.interfaces.IReloadSupport;
import com.alibaba.fastjson.JSONObject;
import cn.pink.core.support.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;

/**
 * 物品|Item 
 * Item.xlsx
 * @author System
 * 此类是系统自动生成类 不要直接修改，修改后也会被覆盖
 */
@ConfigJSON
public class ConfItem extends ConfBase {
	/** 1:物品Sn（ID规则见sheet） */
	public final int sn;
	/** 2:物品名称 */
	public final String name;
	/** 3:物品作用 */
	public final String description;
	/** 1:角色 2:装备 3:货币 4:道具 5:成长道具 6:角色碎片 */
	public final int type;
	/** 子类型 */
	public final int subtype;
	/** 叠加数量默认不限制 */
	public final int overNum;
	/** true直接使用false存入背包 */
	public final boolean useAuto;
	/** 使用公式 */
	public final String[] useFun;
	/** 使用公式参数 */
	public final String[] useParam;

	private ConfItem(JSONObject data) {
		this.sn = data.getIntValue("sn");
		this.name = data.getString("name");
		this.description = data.getString("description");
		this.type = data.getIntValue("type");
		this.subtype = data.getIntValue("subtype");
		this.overNum = data.getIntValue("overNum");
		this.useAuto = data.getBooleanValue("useAuto");
		this.useFun = parseStringArray(data.getString("useFun"), ",");
		this.useParam = parseStringArray(data.getString("useParam"), ",");
	}

	private void reset(JSONObject data) {
        Map<String, Field> fieldMap = tempClassField.get(this.getClass());

		reflectSet(fieldMap.get("sn"), data.getIntValue("sn"));
		reflectSet(fieldMap.get("name"), data.getString("name"));
		reflectSet(fieldMap.get("description"), data.getString("description"));
		reflectSet(fieldMap.get("type"), data.getIntValue("type"));
		reflectSet(fieldMap.get("subtype"), data.getIntValue("subtype"));
		reflectSet(fieldMap.get("overNum"), data.getIntValue("overNum"));
		reflectSet(fieldMap.get("useAuto"), data.getBooleanValue("useAuto"));
		reflectSet(fieldMap.get("useFun"), parseStringArray(data.getString("useFun"), ","));
		reflectSet(fieldMap.get("useParam"), parseStringArray(data.getString("useParam"), ","));
	}

	private static IReloadSupport support = null;
	
	public static void initReloadSupport(IReloadSupport s) {
		support = s;
	}
	
	public static void reload() {
		if (support != null)
			support.beforeReload();
		DATA._init();
		
		if (support != null)
			support.afterReload();
	}

	/**
	 * 获取全部数据
	 * @return
	 */
	public static Collection<ConfItem> findAll() {
		return DATA.getList();
	}

	/**
	 * 通过SN获取数据
	 * @param sn
	 * @return
	 */
	public static ConfItem get(Integer sn) {
		return DATA.getMap().get(sn);
	}

		/**
	 * 通过SN获取数据,如果为null，打印log
	 * @param sn
	 * @return
	 */
	public static ConfItem getNotNull(Integer sn) {
		ConfItem conf = DATA.getMap().get(sn);
		if(conf == null){
			Log.config.error("ConfItem not exit, sn={}", sn);
		}
		return conf;
	}

	/**
	 * 通过SN判断是否拥有该物品（针对装备移除item表的暂时策略）
	 * @param sn
	 * @return
	 */
	public static boolean contains(Integer sn) {
		return DATA.getMap().containsKey(sn);
	}

	/**
	 * 获取全部key
	 * @return
	 */
	public static Set<Integer> findKeys() {
		return DATA.getMap().keySet();
	}

	/**
	 * 通过属性获取单条数据
	 * @param params
	 * @return
	 */
	public static ConfItem getBy(Object...params) {
		List<ConfItem> list = utilBase(DATA.getList(), params);
		if (list.isEmpty()) {
			return null;
		} else {
			return list.get(0);
		}
	}
	
	/**
	 * 通过属性获取数据集合
	 * @param params
	 * @return
	 */
	public static List<ConfItem> findBy(Object...params) {
		return utilBase(DATA.getList(), params);
	}
	public static List<ConfItem> findByType(int type) {
		String key = makeGroupKey(type);
		List<ConfItem> results = DATA.getType().get(key);
		if (results == null) {
			return new ArrayList<>();
		} else {
			return Collections.unmodifiableList(results);
		}
	}

	public static ConfItem getByType(int type) {
		String key = makeGroupKey(type);
		List<ConfItem> results = DATA.getType().get(key);
		if (results == null || results.isEmpty()) {
			return null;
		} else {
			return results.get(0);
		}
	}

	/**
	 * 属性关键字
	 */
	public static final class K {
		/** 1:物品Sn（ID规则见sheet） */
		public static final String sn = "sn";
		/** 2:物品名称 */
		public static final String name = "name";
		/** 3:物品作用 */
		public static final String description = "description";
		/** 1:角色 2:装备 3:货币 4:道具 5:成长道具 6:角色碎片 */
		public static final String type = "type";
		/** 子类型 */
		public static final String subtype = "subtype";
		/** 叠加数量默认不限制 */
		public static final String overNum = "overNum";
		/** true直接使用false存入背包 */
		public static final String useAuto = "useAuto";
		/** 使用公式 */
		public static final String useFun = "useFun";
		/** 使用公式参数 */
		public static final String useParam = "useParam";
	}

	/**
	 * 数据集
	 * 单独提出来也是为了做数据延迟初始化
	 * 避免启动遍历类时，触发了static静态块
	 */
	private static final class DATA {
		/** 全部数据 */
		private static Map<Integer, ConfItem> _map;
		/** index Type */
		private static Map<String, List<ConfItem>> _mapType;

		private static String name = "ConfItem";

		/**
		 * 获取数据的值集合
		 * @return
		 */
		public static Collection<ConfItem> getList() {
			return getMap().values();
		}
		
		/**
		 * 获取Map类型数据集合
		 * @return
		 */
		public static Map<Integer, ConfItem> getMap() {
			// 延迟初始化
			if (_map == null) {
				synchronized (DATA.class) {
					if (_map == null) {
						_init();
					}
				}
			}
			
			return _map;
		}

		static Map<String, List<ConfItem>> getType() {
			getMap();
			return _mapType;
		}

		/**
		 * 初始化数据
		 */
		private static void _init() {
			Map<Integer, ConfItem> dataMap = new TreeMap<>();
			
			// JSON数据
			String confJSON = readConfFile(name);
			if (StringUtils.isBlank(confJSON)) {
				return;
			}

			_mapType = new TreeMap<>();
			// 填充实体数据
			JSONArray confs = (JSONArray)JSONArray.parse(confJSON);
			for (int i = 0 ; i < confs.size() ; i++) {
				JSONObject conf = confs.getJSONObject(i);
				Integer sn = (Integer)conf.get("sn");
				ConfItem config = _map == null ? null : _map.get(sn);
				if(config == null){
					config = new ConfItem(conf);
				}else{
					config.reset(conf);
				}
				dataMap.put(conf.getInteger("sn"), config);

				putMap(_mapType, config, conf.getIntValue("type"));
			}

			// 保存数据
			_map = Collections.unmodifiableMap(dataMap);
		}

	}
    
	/**
	 * 取得属性值
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <T> T getFieldValue(String key) {
		Object value = null;
		switch (key) {
			case "sn": {
				value = this.sn;
				break;
			}
			case "name": {
				value = this.name;
				break;
			}
			case "description": {
				value = this.description;
				break;
			}
			case "type": {
				value = this.type;
				break;
			}
			case "subtype": {
				value = this.subtype;
				break;
			}
			case "overNum": {
				value = this.overNum;
				break;
			}
			case "useAuto": {
				value = this.useAuto;
				break;
			}
			case "useFun": {
				value = this.useFun;
				break;
			}
			case "useParam": {
				value = this.useParam;
				break;
			}
			default: break;
		}
		
		return (T) value;
	}

}